#!/usr/bin/env python

import sys, os, os.path
from xml.dom.minidom import parse
from getopt import getopt

server_url = ""
git_branch = ""
remote_name = ""
manifest_dom = None
tagManifet = None
tagRemote = None
tagDefault = None

def pr_red_info(message):
	print "\033[31m%s\033[0m" % message

def pr_green_info(message):
	print "\033[32m%s\033[0m" % message

def pr_bold_info(message):
	print "\033[1m%s\033[0m" % message

def show_usage():
	pr_bold_info("Usage: %s [options] output" % os.path.basename(sys.argv[0]))
	print "-i, -I, --input: source file directory"
	print "-o, -O, --output: git repo root directory"
	print "-u, -U, --url: target git server url"
	print "-b, -B, --branch: create new branch"
	print "-m, -M, --menifest: default.xml path"
	print "-r, -R, --remote: remote name"

def parse_xml(manifest):
	global manifest_dom, tagManifet, tagRemote, tagDefault
	global git_branch, server_url, remote_name

	manifest_dom = parse(manifest)
	if manifest_dom ==  None:
		return -1

	tagManifet = manifest_dom.getElementsByTagName("manifest").item(0)
	if tagManifet == None:
		pr_red_info("No manifet tag found")
		return -1

	tagRemote = tagManifet.getElementsByTagName("remote").item(0)
	if tagRemote == None:
		pr_red_info("No remote tag found")

	if server_url == "":
		server_url = tagRemote.getAttribute("fetch")

	if remote_name == "":
		remote_name = tagRemote.getAttribute("name")

	tagDefault = tagManifet.getElementsByTagName("default").item(0)
	if tagDefault == None:
		pr_red_info("No default tag found")
		return -1

	if git_branch == "":
		git_branch = tagDefault.getAttribute("revision")

	return 0

def remove_force(path):
	if os.path.isdir(path):
		for name in os.listdir(path):
			remove_force(os.path.join(path, name))
		os.rmdir(path)
	elif os.path.exists(path):
		os.remove(path)

def git_init(source, target):
	pr_bold_info("%s => %s" % (source, target))

	if not os.path.isdir(target):
		remove_force(target)

		if os.system("mkdir %s -p && cd %s && git init --bare --shared" % (target, target)) != 0:
			return -1

	os.chdir(source)

	if not os.path.isdir(".git"):
		if os.system("git init && git add . -f") != 0:
			return -1

		if os.system("git commit -asm \"Add all files to git repo\"") != 0:
			return -1

	os.system("git branch %s" % git_branch)

	if os.system("git push %s %s" % (target, git_branch)) != 0:
		return -1

	try:
		fd = file(os.path.join(target, "HEAD"), "w")
	except:
		pr_red_info("open HEAD failed")
		return -1

	fd.write("ref: refs/heads/%s" % git_branch)
	fd.close()

	return 0

def create_manifest_git(target):
	global tagRemote, tagDefault
	global server_url, remote_name, git_branch

	temp_source = "/tmp/manifest"

	remove_force(temp_source)
	os.makedirs(temp_source)

	tagRemote.setAttribute("fetch", "%s" % server_url.rstrip(" /"))
	tagRemote.setAttribute("name", remote_name)
	tagDefault.setAttribute("revision", git_branch)
	tagDefault.setAttribute("remote", remote_name)

	try:
		fd = file(os.path.join(temp_source, "default.xml"), "w")
	except:
		pr_red_info("Open %s/default.xml failed" % temp_source)
		return -1

	fd.write(manifest_dom.toprettyxml('\t', ''))
	fd.close()

	remove_force(target)

	return git_init(temp_source, target)

def create_repo():
	global server_url, git_branch, remote_name

	try:
		opts, args = getopt(sys.argv[1:],
			"i:I:o:O:u:U:b:B:m:M:r:R:",
			["input=", "output=", "url=", "branch=", "manifest=", "config=", "remote="])
	except:
		show_usage()
		return -1

	if len(args) < 1:
		show_usage()
		return -1

	source_root = "."
	dest_root = ""
	manifest_xml = ""
	remote_name = ""

	for opt in opts:
		if opt[0] in ["-i", "-I", "--input"]:
			source_root = opt[1].rstrip(" /")
		elif opt[0] in ["-o", "-O", "--output"]:
			dest_root = opt[1].rstrip(" /")
		elif opt[0] in ["-u", "-U", "--url"]:
			server_url = opt[1].strip()
		elif opt[0] in ["-b", "-B", "--branch"]:
			git_branch = opt[1].strip()
		elif opt[0] in ["-m", "-M", "--manifest", "--config"]:
			manifest_xml = opt[1]
		elif opt[0] in ["-r", "-R", "--remote"]:
			remote_name = opt[1]
		else:
			pr_red_info("unknown option %s" % opt)
			show_usage()
			return -1

	if dest_root == "":
		if len(args) > 0:
			dest_root = args[0]
		else:
			pr_red_info("dest directory = %s" % dest_root)
			show_usage()
			return -1

	source_root = os.path.abspath(source_root)
	dest_root = os.path.abspath(dest_root)

	if manifest_xml == "":
		manifest_xml = os.path.join(source_root, ".repo/manifest.xml")

	if parse_xml(manifest_xml) < 0:
		pr_red_info("parse xml file %s failed" % manifest_xml)
		show_usage()
		return -1

	if server_url == "":
		server_url = ".."

	if git_branch == "" or remote_name == "":
		pr_red_info("git_branch = %s, remote_name = %s" % (git_branch, remote_name))
		show_usage()
		return -1

	if create_manifest_git(os.path.join(dest_root, "platform/manifest.git")) < 0:
		pr_red_info("create_manifest_git failed")
		return -1

	for project in tagManifet.getElementsByTagName("project"):
		name = project.getAttribute("name")
		path = project.getAttribute("path")
		if name == "" or path == "":
			pr_red_info("No name or path attribute found")
			return -1
		if git_init(os.path.join(source_root, path), "%s/%s.git" % (dest_root, name)) < 0:
			pr_red_info("init git repo %s failed" % name)
			return -1

	return 0

if __name__ == "__main__":
	if create_repo() < 0:
		pr_red_info("Failed")
	else:
		pr_green_info("OK")
